using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using Comteck.Dto.Goods;
using Comteck.Entities.Goods;
using Comteck.Ktt.Services.Infrastructure;
using Comteck.Ktt.Services.Orders;
using ExpressMapper.Extensions;

namespace Comteck.Ktt.Services.Goods {
  /// <summary>
  /// 
  /// </summary>
  public class ProductService : BaseKttService, IProductService {
    private readonly IKttRepository<Product, int> _productRepository;
    private readonly Lazy<ISaleOrderService> saleOrderService;

    public ProductService(IKttUnitOfWork unitOfWork,
      Lazy<ISaleOrderService> saleOrderService) : base(unitOfWork) {
      _productRepository = _unitOfWork.GetRepository<Product, int>();
      this.saleOrderService = saleOrderService;
    }

    /// <summary>
    /// 查询分页主表数据
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<AjaxResponsePage<List<ProductDto>>> GetPageListAsync(ProductQuery model) {
      var result = new AjaxResponsePage<List<ProductDto>>() {
        Size = model.Size,
        Page = model.Page,
      };

      // 查询表达式
      var query = this.GetListQuery(model);

      // search
      result.Total = await query.CountAsync();

      var list = await query.OrderBy(x => x.Id)
        .Skip((Math.Max(model.Page, 1) - 1) * model.Size)
        .Take(model.Size).ToListAsync();
      result.Data = list.MapTo<List<ProductDto>>();

      return result;
    }

    /// <summary>
    /// query
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    private IQueryable<Product> GetListQuery(ProductQuery model) {
      var query = from d in _productRepository.TableUntracked
                  select d;
        // 
        query = query.WhereIIf(model.Code.IsNotNullOrEmpty(), x => x.Code == model.Code)
          .WhereIIf(model.Name.IsNotNullOrEmpty(), x => x.Name.Contains(model.Name));

      return query;
    }

    /// <summary>
    /// 查询分页主表数据
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<IEnumerable<ProductDto>> GetAllAsync() {
      var list = await _productRepository.GetAllAsync();
      return list.MapTo<IEnumerable<ProductDto>>();
    }

    /// <summary>
    /// 查询分页主表数据
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<IEnumerable<ProductDto>> GetListByIdsAsync(List<int> ids) {
      var list = await _productRepository.TableUntracked.Where(x => ids.Contains(x.Id)).ToListAsync();
      return list.MapTo<List<ProductDto>>();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<ProductDto> GetEditModelAsync(int id) {
      ProductDto model;
      if (id <= 0) {
        model = new ProductDto();
      } else {
        var entity = await _productRepository.GetByIdAsync(id);
        model = entity.MapTo<ProductDto>();
      }

      return model;
    }

    /// <summary>
    /// 新增
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<ProductDto>> SaveAsync(ProductDto model) {
      var result = new AjaxResponse<ProductDto>() {
        Code = 0
      };

      try {
        // check
        await this.CheckSaveAsync(model);

        var dbEntity = await _productRepository.GetByIdAsync(model.Id);

        if (dbEntity == null) {
          // add
          dbEntity = model.MapTo<Product>();
          dbEntity.CreateTime = DateTime.Now;
          await _productRepository.AddAsync(dbEntity);
        } else {
          // modify
          model.MapTo(dbEntity);
          await _productRepository.UpdateAsync(dbEntity);
        }

        result.Code = 1;
        result.Data = dbEntity.MapTo<ProductDto>();
      } catch (Exception ex) {
        result.Message = ex.Message;
      }

      return result;
    }

    /// <summary>
    /// 校验合法性
    /// </summary>
    /// <param name="model"></param>
    private async Task CheckSaveAsync(ProductDto model) {
      if (model.Name.IsNullOrEmpty()) {
        throw new ComteckException("商品名称不能为空");
      }

      if (model.Weight < decimal.Zero) {
        throw new ComteckException("商品重量必须大于等于0");
      }

      // 一个用户可以多个分公司，一个分公司只能一个用户
      if (await _productRepository.CountAsync(x => x.Id != model.Id && x.Name == model.Name) > 0) {
        throw new ComteckException($"商品名称 {model.Name} 已存在");
      }
    }

    /// <summary>
    /// 新增
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<IEnumerable<Product>> InsertBatchAsync(IEnumerable<Product> list) {
      await _productRepository.AddRangeAsync(list);
      return list;
    }

    /// <summary>
    /// 新增
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task DeleteAsync(int id) {
      var entity = await _productRepository.GetByIdAsync(id);
      if (entity == null) {
        throw new ComteckException("商品不存在");
      }

      if (await saleOrderService.Value.IsProductUserdAsync(id)) {
        throw new ComteckException("商品已被使用");
      }

      await _productRepository.RemoveAsync(entity);
    }

    /// <summary>
    /// 批量更新
    /// </summary>
    /// <param name="list"></param>
    /// <returns></returns>
    public async Task SaveBatchAsync(IEnumerable<ProductDto> list) {
      if (list.IsNullOrEmpty()) {
        return;
      }

      var dbList = list.MapTo<List<Product>>();
      await _productRepository.UpdateRangeAsync(dbList);
    }
  }
}
